package com.util;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;

@Slf4j
public class Util {
    /**
     * 日期格式列表
     */
    private static List<SimpleDateFormat> patternList = Arrays.asList(
            new SimpleDateFormat("yyyy-MM-dd"),
            new SimpleDateFormat("yyyy/MM/dd"),
            new SimpleDateFormat("yyyyMMdd"),
            new SimpleDateFormat("yyyy-MM-dd HH:mm"));

    /**
     * 日期字符串转日期
     * @param dateStr
     * @return
     */
    public static Date dateStr4Date(String dateStr) {
        if(dateStr==null) return null;
        for (SimpleDateFormat pattern : patternList) {
            try {
                return pattern.parse(dateStr);
            } catch (ParseException e) {
                continue;
            }
        }
        throw new RuntimeException("时间类型转换异常，时间格式应为yyyy-MM-dd或yyyy/MM/dd或yyyyMMdd");
    }

    /**
     * 日期转默认日期字符串
     * @param date
     * @return
     */
    public static String date4String(Date date) {
        if(date==null) return "";
        return patternList.get(0).format(date);
    }

    /**
     * 日期转指定格式的日期字符串
     * @param date
     * @return
     */
    public static String date4String(Date date, String patterStr) {
        return new SimpleDateFormat(patterStr).format(date);
    }

    /**
     * 获取项目根目录
     * @return
     */
    public static String getPath() {
        return Util.class.getResource("/").getPath();
    }

    /**
     * 加载配置文件 *.properties
     * @param dbConfigName
     * @return
     * @throws IOException
     */
    public static Map<String, String> loadConfig(String dbConfigName) throws IOException {
        if (!dbConfigName.endsWith(".properties")) dbConfigName += ".properties";
        //获取当前目录
        String currentPath = Util.class.getResource("").getPath();
        //创建file对象，检查配置文件是否存在
        File file = new File(currentPath + dbConfigName);
        if (!file.exists()) {
            //如不存在获取项目根目录
            currentPath = Util.class.getResource("/").getPath();
            file = new File(currentPath + dbConfigName);
            //再次检查文件是否存在
            if (!file.exists()) {
                //配置文件不存在抛异常
                throw new FileNotFoundException("找不到配置文件：" + dbConfigName);
            }
        }
        FileInputStream fis = new FileInputStream(new File(currentPath + dbConfigName));

        Properties pro = new Properties();
        pro.load(fis);
        Map<String, String> configMap = new HashMap<>();
        pro.forEach((k, v) -> configMap.put(k.toString(), v.toString()));
        fis.close();
        return configMap;
    }

    /**
     * 获取指定验证码的图片缓存对象
     *
     * @param checkCode
     * @return
     */
    public static BufferedImage getImg(String checkCode) {
        return getImg(checkCode, 100, 32);
    }

    /**
     * 获取指定验证码的图片缓存对象
     * @param checkCode
     * @param width
     * @param height
     * @return
     */
    public static BufferedImage getImg(String checkCode, int width, int height) {
        //声明一个的随机数对象
        Random random = new Random();
        //创建图片缓存
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //设置图片大小的
        Graphics gra = image.getGraphics();
        gra.setColor(getRandColor(200, 250)); //设置背景色rand垫底
        gra.fillRect(0, 0, width, height);

        // 绘制随机的干扰线，使图象中的认证码不易被其它程序探测到
        for (int i = 0; i < 40; i++) {
            gra.setColor(getRandColor(100, 200));
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(width);
            int yl = random.nextInt(height);
            gra.drawLine(x, y, xl, yl);
        }
        //绘制文字
        for (int i = 0; i < checkCode.length(); i++) {
            // 设置字体
            gra.setFont(new Font("黑体", Font.BOLD, random.nextInt(4) + 16));
            // 设置字体颜色
            //调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成
            gra.setColor(new Color(20 + random.nextInt(110),
                    20 + random.nextInt(110),
                    20 + random.nextInt(110)));
            //获取文字
            String rand = checkCode.substring(i, i + 1);
            //绘制文字
            gra.drawString(rand, 16 * i + 4 + random.nextInt(4), 22 + random.nextInt(6) - 6);
        }
        //绘制随机的噪点
        for (int i = 0; i < 50; i++) {
            gra.setColor(getRandColor(100, 200));
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            gra.drawRect(x, y, 1, 1);
        }
        //返回图片缓存
        return image;
    }

    /**
     * 获取随机颜色
     * @param fc
     * @param bc
     * @return
     */
    private static Color getRandColor(int fc, int bc) { //给定范围获得随机颜色
        Random random = new Random();
        if (fc > 255) fc = 255;
        if (bc > 255) bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    /**
     * 获取4位验证码
     * @return
     */
    public static String createCheckCode() {
        return Util.createCheckCode(4);
    }

    /**
     * 获取指定位数验证码
     * @param count count>=4  count<=6
     * @return
     */
    public static String createCheckCode(int count) {
        if (count < 4 || count > 6) throw new RuntimeException("生成验证码长度过短或过长！");

        StringBuffer checkCodeBuf = new StringBuffer();
        for (int i = 0; i < count; i++) {
            checkCodeBuf.append(Util.getRandomStr());
        }
        return checkCodeBuf.toString();
    }

    /**
     * 获取一个随机的字母或数字
     * @return
     */
    private static String getRandomStr() {
        Random random = new Random();
        int num = random.nextInt(30) % 3;
        switch (num) {
            case 0:
                num = random.nextInt(10) + 48;
                break;
            case 1:
                num = random.nextInt(26) + 65;
                break;
            case 2:
                num = random.nextInt(26) + 97;
                break;
        }
        return String.valueOf((char) num);
    }


    public static void loadExcelFile(String fileName) {

    }

    /**
     * 保存多个文件，返回文件保存的路径集合
     * @param savePath
     * @param request
     * @return
     * @throws IOException
     * @throws ServletException
     */
    public static List<String> uploadFile(String savePath, HttpServletRequest request) throws IOException, ServletException {
        //保存新的头像文件
        String fullPath = request.getServletContext().getRealPath(savePath);
        File file = new File(savePath);
        if (!file.exists()) {
            file.mkdirs();
        }

        Collection<Part> parts = request.getParts();
        List<String> fileUrlList = new ArrayList<>();
        //遍历文件列表，获取每一个元素
        parts.forEach(part -> {
            if (part.getContentType() != null) {
                //从元素中获取文件名
                String header = part.getHeader("Content-Disposition");
//                System.out.println("header = " + header);
                //截取文件后缀名
                String suffix = header.substring(header.lastIndexOf(".")).replace("\"", "");
                //构建文件名
                String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
                //保存文件
                if (fileName != null && !"".equals(fileName)) {
                    try {
                        part.write(fullPath + fileName);
                        fileUrlList.add(savePath + fileName);
                        log.info("成功上传文件："+savePath + fileName);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        return fileUrlList;
    }



    @Test
    public void testMain() {
        String checkCode = Util.createCheckCode(6);
        System.out.println(checkCode);
        BufferedImage img = Util.getImg(checkCode);
    }
}
